<template>
  <div class="chart-container" :style="{ height: height }">
    <div v-if="loading" class="chart-loading">
      <div class="spinner"></div>
      <span>加载中...</span>
    </div>
    <div v-else-if="error" class="chart-error">
      <i class="fas fa-exclamation-circle"></i>
      <span>{{ error }}</span>
    </div>
    <div v-else-if="!series || series.length === 0" class="chart-empty">
      <i class="fas fa-chart-bar"></i>
      <span>暂无数据</span>
    </div>
    <div v-else ref="chartRef" class="chart-inner"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, nextTick, onBeforeUnmount } from 'vue';
import ApexCharts from 'apexcharts';

interface Series {
  name: string;
  data: (number | null | { x: any; y: any; fillColor?: string; strokeColor?: string })[];
  type?: string; // 允许混合图表（line, column等）
  color?: string;
}

// 组件属性
const props = defineProps({
  // 图表类型
  type: {
    type: String,
    default: 'line',
    validator: (value: string) => [
      'line', 
      'area', 
      'bar', 
      'pie', 
      'donut', 
      'radar', 
      'scatter', 
      'heatmap',
      'mixed'
    ].includes(value)
  },
  // 图表高度
  height: {
    type: String,
    default: '300px'
  },
  // 图表标题
  title: {
    type: String,
    default: ''
  },
  // 图表子标题
  subtitle: {
    type: String,
    default: ''
  },
  // 图表数据系列
  series: {
    type: Array as () => Series[],
    default: () => []
  },
  // x轴分类
  categories: {
    type: Array as () => any[],
    default: () => []
  },
  // 颜色列表
  colors: {
    type: Array as () => string[],
    default: () => ['#5e72e4', '#2dce89', '#fb6340', '#11cdef', '#f5365c', '#8965e0']
  },
  // x轴标题
  xAxisTitle: {
    type: String,
    default: ''
  },
  // y轴标题
  yAxisTitle: {
    type: String,
    default: ''
  },
  // 是否显示图例
  showLegend: {
    type: Boolean,
    default: true
  },
  // 是否显示工具提示
  showTooltip: {
    type: Boolean,
    default: true
  },
  // 是否显示网格线
  showGrid: {
    type: Boolean,
    default: true
  },
  // 是否启用缩放
  enableZoom: {
    type: Boolean,
    default: false
  },
  // 是否能导出
  enableExport: {
    type: Boolean,
    default: false
  },
  // 是否显示DataLabels
  showDataLabels: {
    type: Boolean,
    default: false
  },
  // 是否显示标记点
  showMarkers: {
    type: Boolean,
    default: true
  },
  // 是否平滑曲线（仅适用于线图）
  smooth: {
    type: Boolean,
    default: false
  },
  // 自定义ApexCharts配置项
  customOptions: {
    type: Object,
    default: () => ({})
  }
});

// 组件事件
const emit = defineEmits(['dataPointSelection', 'zoomed', 'legendClick']);

// 内部状态
const chartRef = ref<HTMLElement | null>(null);
const chart = ref<ApexCharts | null>(null);
const loading = ref(false);
const error = ref<string | null>(null);

// 创建图表配置
const createChartOptions = () => {
  // 基础配置
  const options: any = {
    chart: {
      type: props.type === 'mixed' ? 'line' : props.type, // 混合图表默认为line
      height: props.height,
      toolbar: {
        show: props.enableExport,
        tools: {
          download: props.enableExport,
          selection: props.enableZoom,
          zoom: props.enableZoom,
          zoomin: props.enableZoom,
          zoomout: props.enableZoom,
          pan: props.enableZoom,
          reset: props.enableZoom
        }
      },
      zoom: {
        enabled: props.enableZoom
      },
      events: {
        dataPointSelection: (event: any, chartContext: any, config: any) => {
          emit('dataPointSelection', { event, chartContext, config });
        },
        legendClick: (chartContext: any, seriesIndex: number, config: any) => {
          emit('legendClick', { chartContext, seriesIndex, config });
        },
        zoomed: (chartContext: any, { xaxis, yaxis }: any) => {
          emit('zoomed', { chartContext, xaxis, yaxis });
        }
      }
    },
    colors: props.colors,
    series: props.series,
    stroke: {
      curve: props.smooth ? 'smooth' : 'straight',
      width: 2
    },
    dataLabels: {
      enabled: props.showDataLabels
    },
    title: {
      text: props.title,
      align: 'left'
    },
    subtitle: {
      text: props.subtitle,
      align: 'left'
    },
    legend: {
      show: props.showLegend,
      position: 'bottom'
    },
    tooltip: {
      enabled: props.showTooltip,
      theme: 'light',
      shared: true
    },
    markers: {
      size: props.showMarkers ? 4 : 0,
      hover: {
        size: 6
      }
    },
    grid: {
      show: props.showGrid,
      borderColor: '#e0e0e0',
      strokeDashArray: 3
    },
    noData: {
      text: '暂无数据',
      align: 'center',
      verticalAlign: 'middle',
      offsetY: 0
    }
  };

  // 根据图表类型处理特殊配置
  if (['line', 'area', 'bar', 'scatter', 'heatmap', 'mixed'].includes(props.type)) {
    options.xaxis = {
      categories: props.categories,
      title: {
        text: props.xAxisTitle,
        style: {
          fontWeight: 400
        }
      }
    };
    
    options.yaxis = {
      title: {
        text: props.yAxisTitle,
        style: {
          fontWeight: 400
        }
      }
    };
  }

  // 整合自定义配置
  return { ...options, ...props.customOptions };
};

// 初始化图表
const initChart = async () => {
  if (!chartRef.value) {
    console.warn('Chart reference element not found');
    return;
  }
  
  try {
    loading.value = true;
    error.value = null;
    
    // 如果图表已存在，销毁它
    if (chart.value) {
      chart.value.destroy();
      chart.value = null;
    }
    
    // 如果没有数据，不创建图表
    if (!props.series || props.series.length === 0) {
      loading.value = false;
      return;
    }
    
    // 等待DOM更新完成
    await nextTick();
    
    // 再次检查元素是否存在
    if (!chartRef.value || !document.body.contains(chartRef.value)) {
      console.warn('Chart container not in DOM');
      loading.value = false;
      return;
    }
    
    // 创建新图表
    const options = createChartOptions();
    chart.value = new ApexCharts(chartRef.value, options);
    await chart.value.render();
    
  } catch (err: any) {
    error.value = `图表渲染失败: ${err.message || '未知错误'}`;
    console.error('Chart initialization error:', err);
  } finally {
    loading.value = false;
  }
};

// 更新图表
const updateChart = () => {
  if (!chart.value) {
    initChart();
    return;
  }
  
  const options = createChartOptions();
  chart.value.updateOptions(options);
};

// 监听属性变化
watch(() => props.series, updateChart, { deep: true });
watch(() => props.categories, updateChart, { deep: true });
watch(() => props.type, initChart);
watch(() => props.customOptions, updateChart, { deep: true });

// 生命周期钩子
onMounted(initChart);

onBeforeUnmount(() => {
  try {
    if (chart.value) {
      chart.value.destroy();
      chart.value = null;
    }
  } catch (err) {
    console.error('Error destroying chart:', err);
  }
});
</script>

<style scoped>
.chart-container {
  position: relative;
  width: 100%;
  background-color: #fff;
  border-radius: 8px;
  overflow: hidden;
}

.chart-inner {
  width: 100%;
  height: 100%;
}

.chart-loading,
.chart-error,
.chart-empty {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: rgba(255, 255, 255, 0.7);
  color: #666;
  font-size: 14px;
}

.chart-error {
  color: #f5365c;
}

.chart-error i,
.chart-empty i {
  font-size: 32px;
  margin-bottom: 10px;
}

.spinner {
  width: 30px;
  height: 30px;
  border: 3px solid #f3f3f3;
  border-top: 3px solid #5e72e4;
  border-radius: 50%;
  margin-bottom: 10px;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
</style> 
 